package de.jmda.sample.xml;

import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;

import org.apache.commons.lang3.StringUtils;

import de.jmda.core.mproc.ProcessingUtilities;
import de.jmda.core.mproc.Processor;

public class JAXBIndexDataBuilder
{
	private Map<PackageElement, Set<TypeElement>> typesByPackage =
	    new HashMap<PackageElement, Set<TypeElement>>();

	public JAXBIndexDataBuilder(Collection<TypeElement> typeElements)
	{
		for (TypeElement typeElement : typeElements)
		{
			PackageElement packageElement =
			    ProcessingUtilities.getPackageOf(typeElement);

			Set<TypeElement> types = typesByPackage.get(packageElement);

			if (types == null)
			{
				types = new HashSet<TypeElement>();
			}

			types.add(typeElement);
			typesByPackage.put(packageElement, types);
		}
	}

	public Map<File, Set<String>> getIndexFileData()
	{
		Map<File, Set<String>> result = new HashMap<File, Set<String>>();

		for (PackageElement packageElement : typesByPackage.keySet())
		{
			// prepare storage for simple type names of package element's types
			Set<String> typenames = new HashSet<String>();

			// add simple names of all type elements in package element's types to
			// types
			for (TypeElement typeElement : typesByPackage.get(packageElement))
			{
				typenames.add(typeElement.getSimpleName().toString());
			}

			// get source file for first type element in package element's type
			// elements
			File sourceFile =
					Processor.getSourceFile(
							typesByPackage.get(packageElement).iterator().next());

			// use parent file (directory) of source file as key for result
			result.put(sourceFile.getParentFile(), typenames);
		}

		return result;
	}
	
	public String getPackageList()
	{
		Set<String> result = new HashSet<String>();

		for (PackageElement packageElement : typesByPackage.keySet())
		{
			result.add(packageElement.getQualifiedName().toString());
		}
		
		return StringUtils.join(result, ":");
	}

	public static Map<File, Set<String>> build(File sourceRoot)
	{
		JAXBIndexDataBuilder builder =
				new JAXBIndexDataBuilder(XMLRootElementProcessor.process(sourceRoot));
		
		return builder.getIndexFileData();
	}
}